package com.xlh.service.course.impl;

import com.google.common.collect.Lists;
import com.xlh.dto.course.ChapterBasicInfoDTO;
import com.xlh.dto.course.TaskDTO;
import com.xlh.enums.course.ChapterEnum;
import com.xlh.enums.course.ChapterTypeEnum;
import com.xlh.exception.common.BadRequestException;
import com.xlh.exception.common.GlobalException;
import com.xlh.param.course.CreateOrUpdateTaskParam;
import com.xlh.param.course.TaskInfoParam;
import com.xlh.pojo.course.Chapter;
import com.xlh.pojo.course.ChapterBasic;
import com.xlh.service.course.ChapterService;
import com.xlh.service.course.TaskService;
import com.xlh.util.BeanUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 课程
 * <p>
 * Created by lx on 2019/1/28.
 */
@Service
public class TaskServiceImpl implements TaskService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TaskServiceImpl.class);

    @Autowired
    private ChapterService chapterService;

    @Override
    public List<TaskDTO> listTask(Long courseId, Long chapterId, TaskInfoParam param) {

        // 检查章节是否正确
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                Lists.newArrayList(courseId), Lists.newArrayList(chapterId), null, ChapterEnum.CHAPTER);
        if (CollectionUtils.isEmpty(chapters)) {
            throw new BadRequestException();
        }

        // 获取任务
        List<ChapterBasicInfoDTO> data = chapterService.listTask(Lists.newArrayList(chapterId), param.getInfo());
        return convertListTask(data);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskSort(Long courseId, Long chapterId, List<Long> taskIds) {

        // 检查
        if (CollectionUtils.isEmpty(taskIds)) {
            throw new BadRequestException("当前章节下没有任务，调整顺序失败。");
        }
        List<ChapterBasicInfoDTO> data = chapterService.listTask(Lists.newArrayList(chapterId), null);
        List<Long> dbTaskIds = data.stream().map(ChapterBasicInfoDTO::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEqualCollection(dbTaskIds, taskIds)) {
            throw new BadRequestException("任务数据有更新，请重新刷新后再调整任务顺序");
        }

        // 转换数据并修改数据库
        chapterService.updateBatch(convertUpdateChapter(taskIds));

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createTask(Long chapterId, CreateOrUpdateTaskParam param) {

        // 获取章节信息
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                null, Lists.newArrayList(chapterId), null, ChapterEnum.CHAPTER);
        ChapterBasicInfoDTO chapter = CollectionUtils.isEmpty(chapters) ? null : chapters.get(0);

        // 检查并获取数据库任务信息
        List<ChapterBasicInfoDTO> dbTasks = checkCreateTaskAndGetDBTask(chapter, param);

        // 转换数据
        ChapterBasic insertChapterBasic = convertChapterBasic(chapter, param.getName(), chapter.getStepType());
        Chapter insertTask = convertChapter(chapter, dbTasks.size());

        // 插入数据库
        chapterService.createChapter(insertChapterBasic, insertTask);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTask(Long taskId, CreateOrUpdateTaskParam param) {

        // 获取任务信息
        List<ChapterBasicInfoDTO> chapters = chapterService.listChapter(
                null, Lists.newArrayList(taskId), null, ChapterEnum.TASK);
        ChapterBasicInfoDTO dbTask = CollectionUtils.isEmpty(chapters) ? null : chapters.get(0);

        // 检查是否允许修改
        checkUpdateTask(dbTask, param);

        // 转换数据
        ChapterBasic updateData = convertChapterBasic(dbTask, param.getName(), dbTask.getStepType());

        // 修改数据库
        chapterService.updateChapterBasicsOrChapter(updateData, dbTask, ChapterEnum.TASK);

    }

    private ChapterBasic convertChapterBasic(ChapterBasicInfoDTO chapter, String name, Integer stepType) {
        ChapterBasic chapterBasic = new ChapterBasic();
        chapterBasic.setName(StringUtils.isBlank(name) ? chapter.getName() : name);
        chapterBasic.setType(chapter.getType());
        chapterBasic.setStepType(stepType);
        return chapterBasic;
    }

    private Chapter convertChapter(ChapterBasicInfoDTO chapter, Integer orderNumber) {
        Chapter task = new Chapter();
        task.setParentId(chapter.getId());
        task.setCourseId(chapter.getCourseId());
        task.setOrderNumber(orderNumber + 1);
        return task;
    }

    private List<ChapterBasicInfoDTO> checkCreateTaskAndGetDBTask(
            ChapterBasicInfoDTO chapter, CreateOrUpdateTaskParam param) {

        // 检查章节是否包含实验课
        if (!isContainsExperiment(chapter)) {
            throw new BadRequestException();
        }

        // 若章节是单任务，数据库有任务数据，则不增加任务
        List<ChapterBasicInfoDTO> dbTasks = chapterService.listTask(Lists.newArrayList(chapter.getId()), null);
        if (CollectionUtils.isNotEmpty(dbTasks) && !ChapterTypeEnum.isManyExperiment(chapter.getType())) {
            throw new GlobalException("当前章节不是多任务，无法再次添加任务");
        }

        // 检查任务名称是否重复
        checkTaskNameIsExist(dbTasks, param.getName(), null);

        return dbTasks;

    }

    private void checkUpdateTask(ChapterBasicInfoDTO dbTask, CreateOrUpdateTaskParam param) {

        // 检查章节是否包含实验课
        if (!isContainsExperiment(dbTask)) {
            throw new BadRequestException();
        }

        // 获取数据库任务数据
        List<ChapterBasicInfoDTO> dbTasks = chapterService.listTask(Lists.newArrayList(dbTask.getParentId()), null);

        // 检查任务名称是否重复
        checkTaskNameIsExist(dbTasks, param.getName(), dbTask.getId());
    }

    private boolean isContainsExperiment(ChapterBasicInfoDTO data) {
        return data != null && ChapterTypeEnum.isContainsExperiment(data.getType());
    }

    private void checkTaskNameIsExist(List<ChapterBasicInfoDTO> dbTasks, String name, Long taskId) {
        if (dbTasks.stream()
                .filter(chapterBasicInfoDTO -> {
                    if (Objects.equals(taskId, chapterBasicInfoDTO.getId())) {
                        return false;
                    }
                    return Objects.equals(chapterBasicInfoDTO.getName(), name);
                }).count() > 0) {
            throw new GlobalException("任务名称已存在");
        }
    }

    private List<Chapter> convertUpdateChapter(List<Long> taskIds) {
        return taskIds.stream().map(taskId -> {
            Chapter chapter = new Chapter();
            chapter.setId(taskId);
            return chapter;
        }).collect(Collectors.toList());
    }

    private List<TaskDTO> convertListTask(List<ChapterBasicInfoDTO> data) {
        List<TaskDTO> taskDTOS = BeanUtil.batchTransform(TaskDTO.class, data);
        for (int i = 0; i < taskDTOS.size(); i++) {
            taskDTOS.get(i).setOrderNumberStr("任务" + String.format("%02d", i + 1));
        }
        return taskDTOS;
    }

}
